#include <clusnet/net/TcpClient.h>
#include <clusnet/base/Logging.h>
#include <iostream>

int main(int argc, char* argv[])
{
    InitLogging();
    if (argc != 3)
    {
        LOG(ERROR) << "Usage: TcpClient_test <host> <port>";
        return 1;
    }

    boost::asio::io_context io_context;

    clusnet::net::TcpClientPtr client = std::make_shared<clusnet::net::TcpClient>(io_context, argv[1], argv[2]);

    client->setNewConnectionCallback([](clusnet::net::TcpConnectionPtr& conn)
    {
        LOG(INFO) << "connect to " << conn->remoteEndpoint().address() << ":" << conn->remoteEndpoint().port() << " from " << conn->localEndpoint().address() << ":" << conn->localEndpoint().port();
        conn->safeStartReceive();
    });
    client->setCloseCallback([](clusnet::net::TcpConnectionPtr& conn)
    {
        LOG(INFO) << "connect close. remote address: " << conn->remoteEndpoint().address() << ":" << conn->remoteEndpoint().port();
    });
    client->setWriteCompleteCallback([](clusnet::net::TcpConnectionPtr& conn, const clusnet::net::TcpDataPacketPtr& data)
    {
        LOG(INFO) << "send to " << conn->remoteEndpoint().address() << ":" << conn->remoteEndpoint().port() << " " << data->dataLength() << " bytes";
    });
    client->setMessageCallback([](clusnet::net::TcpConnectionPtr& conn, clusnet::net::TcpUniqDataPacketPtr&& data)
    {
        LOG(INFO) << "recv from " << conn->remoteEndpoint().address() << ":" << conn->remoteEndpoint().port() << " " << data->dataLength() << " bytes. data: " << data->body();
    });

    client->safeStartConnect();

    std::thread t([&io_context]() { io_context.run(); });

    std::string line;
    while (std::cin >> line)
    {
        clusnet::net::TcpDataPacketPtr data(new clusnet::net::TcpDataPacket);
        data->setBodyLength(line.length());
        std::memcpy(data->body(), line.c_str(), line.length() + 1);
        client->safeAsyncWrite(data);
        if (line == "stop")
        {
            client->safeClose();
            break;
        }
    }

    t.join();

    return 0;
}
